#ifndef __GAME_REGISTRY_HPP__
#define __GAME_REGISTRY_HPP__

#include <mutex>
#include "SimpleSingleton.hpp"
#include "entt/entt.hpp"

namespace PocketSurvival
{
    class GameRegistry : public SimpleSingletonItem
    {
    public:
        entt::registry registry;
        std::mutex registryMutex;

        template <class T>
        [[nodiscard]] decltype(auto) view()
        {
            std::lock_guard<std::mutex> lk(registryMutex);
            return registry.view<T>();
        }

        inline entt::entity create(entt::entity entity)
        {
            // std::lock_guard<std::mutex> lk(registryMutex);
            return registry.create(entity);
        }

        inline uint16_t destroy(entt::entity entity)
        {
            // std::lock_guard<std::mutex> lk(registryMutex);
            return registry.destroy(entity);
        }

        template <typename T>
        [[nodiscard]] decltype(auto) get(entt::entity entity)
        {
            // std::lock_guard<std::mutex> lk(registryMutex);
            return registry.get<T>(entity);
        }

        template <typename T>
        [[nodiscard]] decltype(auto) try_get(entt::entity entity)
        {
            // std::lock_guard<std::mutex> lk(registryMutex);
            return registry.try_get<T>(entity);
        }

        template <typename Type, typename... Args>
        decltype(auto) emplace(entt::entity entity, Args &&...args)
        {
            // std::lock_guard<std::mutex> lk(registryMutex);
            return registry.emplace<Type>(entity, std::forward<Args>(args)...);
        }

        template <typename Type>
        decltype(auto) storage(const entt::id_type id)
        {
            return registry.storage<Type>(id);
        }

        inline bool valid(entt::entity entity)
        {
            // std::lock_guard<std::mutex> lk(registryMutex);
            return registry.valid(entity);
        }
    };

} // namespace PocketSurvival

#endif
